/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Application.h"
#include "HttpUrl.h"
#include "fileCache.h"

string Application::g_databaseDir = "";
string Application::g_strCachePath = "";
ArkWeb_ControllerAPI *Application::g_controller = NULL;
ArkWeb_ComponentAPI *Application::g_component = NULL;
NativeResourceManager *Application::g_resourceManager = NULL;
ArkWeb_CookieManagerAPI *Application::g_cookieManage = NULL;
string Application::g_strTmpUrl = "";
void* Application::g_connPoolManage = NULL;
void* Application::g_httpGroupRunner = NULL;
void* Application::g_memPool = NULL;
void* Application::g_env = NULL;
void* Application::g_cordovaViewController = NULL;
string Application::g_strPushInfoBeforeInit = "";
string Application::g_strNotificationBeforeInit = "";
vector<string> Application::g_vecCustomSchemes;
vector<string> Application::g_vecWebTag;
vector<string> Application::g_vecProtocolUrl;
map<string, vector<string> > Application::s_mapWebTagToCustomHttpHeaders;
map<string, bool> Application::s_mapWebTagToIsAllowCredentials;
std::mutex Application::s_mutex;
map<string, map<string, string> > Application::s_mapWebTagToResource;
map<uintptr_t, string> Application::s_mapSchemeHandlerToWebTag;
map<string, void*> Application::s_mapFunctionRefresh;
napi_threadsafe_function Application::g_tsfn = nullptr;
string Application::g_strHotCodeUpdateDirectory = "";

void Application::putSchemeHandlerWebTag(const void* pSchemeHandler, const string& strWebTag)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    uintptr_t  upSchemeHandler = reinterpret_cast<uintptr_t>(pSchemeHandler);
    s_mapSchemeHandlerToWebTag[upSchemeHandler] = strWebTag;
}
void Application::pushResource(const string& strWebTag, const string& strSrc, const string& strObj)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    if(s_mapWebTagToResource.find(strWebTag) != s_mapWebTagToResource.end()) {
        map<string, string> & mapSrcObj = s_mapWebTagToResource[strWebTag];
        mapSrcObj[strSrc] = strObj;
    } else {
        map<string, string> mapSrcObj;
        mapSrcObj[strSrc] = strObj;
        s_mapWebTagToResource[strWebTag] = mapSrcObj;
    }
}

string Application::getResourceObj(const void* pSchemeHandler, const string& strSrc)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    uintptr_t  upSchemeHandler = reinterpret_cast<uintptr_t>(pSchemeHandler);
    if(s_mapSchemeHandlerToWebTag.find(upSchemeHandler) == s_mapSchemeHandlerToWebTag.end()) {
        return strSrc;
    }
    string strWebTag = s_mapSchemeHandlerToWebTag[upSchemeHandler];
    if(s_mapWebTagToResource.find(strWebTag) == s_mapWebTagToResource.end()) {
        return strSrc;
    }
    map<string, string> & mapSrcObj = s_mapWebTagToResource[strWebTag];
    if(mapSrcObj.find(strSrc) == mapSrcObj.end()) {
        return strSrc;
    }
    return mapSrcObj[strSrc];
}

void Application::clearResource(const string& strWebTag)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    s_mapWebTagToResource.erase(strWebTag);
}

void Application::addCustomHttpHeaders(const string& strWebTag, const string& strCustomerHttpHeaders)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    vector<string> vecCustomerHttpHeaders;
    HttpUrl::SplitString(strCustomerHttpHeaders, ",", vecCustomerHttpHeaders);
    vecCustomerHttpHeaders.push_back("Content-Type");//预添加
    vecCustomerHttpHeaders.push_back("Authorization");
    HttpUrl::DiffContData<string>(vecCustomerHttpHeaders);
    s_mapWebTagToCustomHttpHeaders[strWebTag] = vecCustomerHttpHeaders;
}

string Application::getCustomHttpHeaders(const void* pSchemeHandler)
{
    string strRet = "Content-Type";
    std::lock_guard<std::mutex> guard(s_mutex);
    uintptr_t  upSchemeHandler = reinterpret_cast<uintptr_t>(pSchemeHandler);
    if(s_mapSchemeHandlerToWebTag.find(upSchemeHandler) == s_mapSchemeHandlerToWebTag.end()) {
        return strRet;
    }
    string strWebTag = s_mapSchemeHandlerToWebTag[upSchemeHandler];
    if(s_mapWebTagToCustomHttpHeaders.find(strWebTag) == s_mapWebTagToCustomHttpHeaders.end()) {
        return strRet;
    }
    vector<string> & vecHeader = s_mapWebTagToCustomHttpHeaders[strWebTag];
    for(int i=0; i<vecHeader.size(); i++) {
        strRet += ",";
        strRet += vecHeader[i];
    }
    
    return strRet;
}

void Application::addIsAllowCredentials(const string& strWebTag, const bool isAllowCredentials)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    s_mapWebTagToIsAllowCredentials[strWebTag] = isAllowCredentials;
}
bool Application::getIsAllowCredentials(const void* pSchemeHandler)
{
    bool isRet = false;
    std::lock_guard<std::mutex> guard(s_mutex);
    uintptr_t  upSchemeHandler = reinterpret_cast<uintptr_t>(pSchemeHandler);
    if(s_mapSchemeHandlerToWebTag.find(upSchemeHandler) == s_mapSchemeHandlerToWebTag.end()) {
        return isRet;
    }
    string strWebTag = s_mapSchemeHandlerToWebTag[upSchemeHandler];
    if(s_mapWebTagToIsAllowCredentials.find(strWebTag) == s_mapWebTagToIsAllowCredentials.end()) {
        return isRet;
    }
    
    return s_mapWebTagToIsAllowCredentials[strWebTag];
}

void Application::removeSchemeHandlerWebTag(const string & strWebTag) {
    std::lock_guard<std::mutex> guard(s_mutex);
    for (auto it = s_mapSchemeHandlerToWebTag.begin(); it != s_mapSchemeHandlerToWebTag.end(); ) {
        if (it->second == strWebTag) {
            it = s_mapSchemeHandlerToWebTag.erase(it); 
            break;
        } else {
            ++it;
        }
    }
    
    for(int i=0; i<g_vecWebTag.size(); i++) {
        if(g_vecWebTag[i] == strWebTag) {
            g_vecWebTag.erase(g_vecWebTag.begin()+i);
            break;
        }
    }
    
    s_mapWebTagToCustomHttpHeaders.erase(strWebTag);
    s_mapWebTagToIsAllowCredentials.erase(strWebTag);
}

bool Application::isValidSchemeHandler(const void* pSchemeHandler) 
{
    std::lock_guard<std::mutex> guard(s_mutex);
    uintptr_t  upSchemeHandler = reinterpret_cast<uintptr_t>(pSchemeHandler);
    if(s_mapSchemeHandlerToWebTag.find(upSchemeHandler) != s_mapSchemeHandlerToWebTag.end()) {
        return true;
    }
    return false;
}

bool  Application::isValidWebTag(const string& strWebTag)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    if(s_mapFunctionRefresh.find(strWebTag) != s_mapFunctionRefresh.end()) {
        return true;
    }
    return false;
}

void Application::addFunctionRefresh(const string& strWebTag, void* pFunctionRefresh)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    s_mapFunctionRefresh[strWebTag] = pFunctionRefresh;
}

void* Application::getFunctionRefresh(const string& strWebTag)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    if(s_mapFunctionRefresh.find(strWebTag) != s_mapFunctionRefresh.end()) {
        return s_mapFunctionRefresh[strWebTag];
    } 
    return nullptr;
}
void Application::delFunctionRefresh(const string& strWebTag)
{
    std::lock_guard<std::mutex> guard(s_mutex);
    if(s_mapFunctionRefresh.find(strWebTag) != s_mapFunctionRefresh.end()) {
       s_mapFunctionRefresh.erase(strWebTag);
    }
}

string Application::getFirstWebTag()
{
    std::lock_guard<std::mutex> guard(s_mutex);
    if(!s_mapFunctionRefresh.empty()) {
        return s_mapFunctionRefresh.begin()->first;
    }
    return "";
}

vector<string> Application::getAllWebTag()
{
    std::lock_guard<std::mutex> guard(s_mutex);
    vector<string> vecWebTag;
    for(auto it=s_mapFunctionRefresh.begin(); it != s_mapFunctionRefresh.end(); it++) {
        vecWebTag.push_back(it->first);
    }
    return vecWebTag;
}